package cc.rengu.igas.mcps.core.service.trans.scanpay;

import cc.rengu.igas.channel.alipay.facade.request.AliGetAuthCodeRequest;
import cc.rengu.igas.channel.alipay.facade.response.AliGetAuthCodeResponse;
import cc.rengu.igas.channel.wechat.facade.request.WechatGetAuthCodeRequest;
import cc.rengu.igas.channel.wechat.facade.response.WechatGetAuthCodeResponse;
import cc.rengu.igas.channel.wechat.facade.result.Result;
import cc.rengu.igas.mcps.common.constant.McpsParamConstant;
import cc.rengu.igas.mcps.common.enums.RespCodeEnum;
import cc.rengu.igas.mcps.core.service.base.QrManageService;
import cc.rengu.igas.mcps.facade.base.Header;
import cc.rengu.igas.mcps.facade.request.GetUserAuthCodeRequest;
import cc.rengu.igas.mcps.facade.response.GetUserAuthCodeResponse;
import cc.rengu.igas.share.core.model.MchntInfo;
import cc.rengu.igas.share.core.model.PlatMchntInfo;
import cc.rengu.igas.share.core.model.QrCodeInfo;
import cc.rengu.igas.share.core.realize.BompService;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.BompServiceImpl;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.constant.TreeNodeConstant;
import cc.rengu.oltp.service.common.dao.MchntOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.UserOrderInfoMapper;
import cc.rengu.oltp.service.common.dao.impl.MchntOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.dao.impl.UserOrderInfoMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MchntOrderInfo;
import cc.rengu.oltp.service.common.entity.UserOrderInfo;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.utility.util.ConvertUtil;
import cc.rengu.oltp.utility.util.StringUtil;
import cc.rengu.oltp.utility.util.XmlTreeUtil;
import com.alibaba.fastjson.JSON;

import java.net.URLDecoder;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 获取微信授权码.
 */
public class McpsGetUserAuthCodeService extends QrManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        GetUserAuthCodeRequest request = new GetUserAuthCodeRequest();
        // 读取存在xml树里的实体类
        ConvertUtil.convertOutput(request);
        xmlTreeUtil.setXmlTreeStringValue(TreeNodeConstant.FRONT_SEQ_NUM, request.getHeader().getTraceNo());
        return request;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        GetUserAuthCodeRequest getUserAuthCodeRequest = (GetUserAuthCodeRequest) request;
        Header header = getUserAuthCodeRequest.getHeader();
        String authChannel = getUserAuthCodeRequest.getAuthChannel();
        String qrUrl = getUserAuthCodeRequest.getQrCode();

        //是否单笔订单(true-是,false-否),默认单笔
        boolean isSingle = true;
        //获取交易的商户号
        String mchntNo = "";
        if (StringUtil.isEmptyOrNull(qrUrl)) {
            rglog.debug("公众号支付<{}>", JSON.toJSONString(getUserAuthCodeRequest));
        } else {
            /*判断是否银标码：收银台域名?qrCode=https//95516.com/xxxx*/
            if (qrUrl.contains("qr.95516.com")) {
                int qrIndex = qrUrl.indexOf("qrCode=");
                if (qrIndex < 0) {
                    rglog.error("无效二维码<{}>", qrUrl);
                    throw new BizException(RespCodeEnum.GET_QRCODE_INVALID.getRespCode(), RespCodeEnum.GET_QRCODE_INVALID.getRespDesc());
                }
                qrUrl = qrUrl.substring(qrIndex + 7);
                /*银联回调时url编码了,此时urldecode*/
                qrUrl = URLDecoder.decode(qrUrl, "UTF-8");
            }
            rglog.info("实际二维码url<{}>", qrUrl);
            //判断二维码类型
            int lastIndex = qrUrl.lastIndexOf("inf=");
            if (lastIndex < 0) {
                rglog.error("二维码<{}>格式错误", qrUrl);
                throw new BizException(RespCodeEnum.GET_QRCODE_INVALID.getRespCode(), RespCodeEnum.GET_QRCODE_INVALID.getRespDesc());
            }
            String qrCodeType = qrUrl.substring(lastIndex + 4, lastIndex + 5);

            if ("D".equals(qrCodeType)) {

                rglog.debug("动态二维码交易，根据用户订单表获取交易商户号");
                UserOrderInfoMapper userOrderInfoMapper = new UserOrderInfoMapperImpl();
                UserOrderInfo userOrderInfo = userOrderInfoMapper.selectUserOrderInfoByOrderUrl(getUserAuthCodeRequest.getHeader().getInstId(), qrUrl);
                if (userOrderInfo == null) {
                    rglog.error("用户订单表中不存在该动态二维码交易记录,instId:<{}>,orderUrl:<{}>", getUserAuthCodeRequest.getHeader().getInstId(), qrUrl);
                    throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
                }
                //获取商户订单
                MchntOrderInfoMapper mchntOrderInfoMapper = new MchntOrderInfoMapperImpl();
                List<MchntOrderInfo> mchntOrderInfos = mchntOrderInfoMapper.selectMchntOrderInfoBySysSeqNum(userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());
                if (null == mchntOrderInfos || mchntOrderInfos.isEmpty()) {
                    rglog.info("商户订单不存在,instId:<{}>,sysSeqNum:<{}>", userOrderInfo.getInstId(), userOrderInfo.getSysSeqNum());
                    throw new BizException(RespCodeEnum.ORDER_NOEXIT.getRespCode(), RespCodeEnum.ORDER_NOEXIT.getRespDesc());
                }

                //合并订单支付的时候商户号取平台商户号
                if (mchntOrderInfos.size() == 1) {
                    rglog.info("单笔订单支付，商户号取商户订单表中的商户号.mchntNo:<{}>", mchntOrderInfos.get(0).getMchntNo());
                    mchntNo = mchntOrderInfos.get(0).getMchntNo();
                } else {
                    if ("ALIPAY".equals(authChannel.toUpperCase())) {
                        rglog.info("支付宝支付不支持合并订单支付");
                        throw new BizException(RespCodeEnum.TRADE_NOT_SUPPORT.getRespCode(), RespCodeEnum.TRADE_NOT_SUPPORT.getRespDesc());
                    }
                    rglog.info("合并订单支付商户号取平台商户号，platMchntNo:<{}>", userOrderInfo.getGroupMchntNo());
                    mchntNo = userOrderInfo.getGroupMchntNo();
                    isSingle = false;
                }
            } else if ("S".equals(qrCodeType)) {

                rglog.debug("静态码交易，根据二维码明细表判断二维码是否存在并获取商户号");
                //校验二维码信息
                BompService bompService = new BompServiceImpl();
                QrCodeInfo qrCodeInfo = bompService.getQrCodeInfo(header.getInstId(), qrUrl, null);
                if (null == qrCodeInfo) {
                    rglog.error("二维码信息不存在，交易阻断");
                    throw new BizException(RespCodeEnum.GET_QRCODE_INVALID.getRespCode(), RespCodeEnum.GET_QRCODE_INVALID.getRespDesc());
                }
                mchntNo = qrCodeInfo.getMchntNo();
            } else {

                rglog.error("二维码<{}>格式错误", qrUrl);
                throw new BizException(RespCodeEnum.GET_QRCODE_INVALID.getRespCode(), RespCodeEnum.GET_QRCODE_INVALID.getRespDesc());
            }
        }
        //区分支付宝与微信
        String authUrl;
        if ("WECHAT".equals(authChannel.toUpperCase())) {
            authUrl = wechatGetAuthCodeUrl(getUserAuthCodeRequest, mchntNo, isSingle);
        } else if ("ALIPAY".equals(authChannel.toUpperCase())) {
            authUrl = aliGetAuthCodeUrl(getUserAuthCodeRequest, mchntNo);
        } else {
            rglog.error("暂不支持获取该渠道授权,机构号:<{}>, AuthChannel:<{}>", header.getInstId(), getUserAuthCodeRequest.getAuthChannel());
            throw new BizException(RespCodeEnum.CHANEL_NOT_SUPPORT.getRespCode(), RespCodeEnum.CHANEL_NOT_SUPPORT.getRespDesc());
        }

        //组装应答信息
        GetUserAuthCodeResponse getUserAuthCodeResponse = new GetUserAuthCodeResponse();
        getUserAuthCodeResponse.setHeader(getUserAuthCodeRequest.getHeader());
        getUserAuthCodeResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        getUserAuthCodeResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        getUserAuthCodeResponse.setAuthUrl(authUrl);
        BizResponse<GetUserAuthCodeResponse> bizResponse = new BizResponse<>();
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(getUserAuthCodeResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        GetUserAuthCodeResponse getUserAuthCodeResponse = (GetUserAuthCodeResponse) bizResponse.getResult();
        ConvertUtil.convertInput(getUserAuthCodeResponse);
    }


    /**
     * 微信获取authUrl调用通道
     *
     * @param request  请求体
     * @param mchntNo  商户号
     * @param isSingle 是否单笔订单(true-是,false-否)
     * @return authUrl
     * @throws Exception 异常
     */
    private String wechatGetAuthCodeUrl(GetUserAuthCodeRequest request, String mchntNo, boolean isSingle) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        List<ChannelCallCfg> txnNumList = txnInfo.getChannelCallCfgList().stream().filter(item -> ChannelEnum.WXZF.getChannelType().equals(item.getCallChannelId())).collect(Collectors.toList());
        if (txnNumList.isEmpty()) {
            rglog.error("未配置微信用户授权的通道交易映射关系");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }
        if (!StringUtil.isEmptyOrNull(mchntNo)) {
            //校验微信商户是否存在
            MchntService mchntService = new MchntServiceImpl();
            if (isSingle) {
                MchntInfo mchntInfo = mchntService.getMchntInfo(request.getHeader().getInstId(), mchntNo);
                if (null == mchntInfo) {
                    rglog.error("商户信息表中不存在该商户信息");
                    throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                }
            } else {
                PlatMchntInfo platMchntInfo = mchntService.getPlatMchntInfo(request.getHeader().getInstId(), mchntNo);
                if (null == platMchntInfo) {
                    rglog.error("平台商户信息表中不存在该商户信息");
                    throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
                }
            }
        }
        cc.rengu.igas.channel.wechat.facade.base.Header wechatHeader = new cc.rengu.igas.channel.wechat.facade.base.Header();
        wechatHeader.setVersion("1.0.0");
        wechatHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        wechatHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        wechatHeader.setTxnNum(txnNumList.get(0).getCallChannelTxn());
        wechatHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        wechatHeader.setInstId(request.getHeader().getInstId());
        wechatHeader.setSrcSysId(AppParamConstant.IGAS);
        wechatHeader.setChanlId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID));
        wechatHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + txnNumList.get(0).getCallIndex());

        WechatGetAuthCodeRequest wechatGetAuthCodeRequest = new WechatGetAuthCodeRequest();
        wechatGetAuthCodeRequest.setHeader(wechatHeader);
        wechatGetAuthCodeRequest.setChannelId(ChannelEnum.WXZF.getChannelType());
        wechatGetAuthCodeRequest.setRedirectUrl(request.getRedirectUrl());
        if (!StringUtil.isEmptyOrNull(request.getQrCode())) {
            String qrCode = request.getQrCode();
            int index = qrCode.indexOf("inf=");
            wechatGetAuthCodeRequest.setState(qrCode.substring(index + 4));
        }
        rglog.debug("dubbo请求体:<{}>", JSON.toJSONString(wechatGetAuthCodeRequest));
        DubboService dubboService = new DubboServiceImpl();
        Result<WechatGetAuthCodeResponse> wechatResponse;
        try {
            wechatResponse = (Result<WechatGetAuthCodeResponse>) dubboService.callDubboService("wechatPubService", "getAuthCode", wechatGetAuthCodeRequest);
        } catch (Exception e) {
            rglog.error("微信获取authCode服务调用异常:<{}>", e);
            wechatResponse = null;
        }
        if (null == wechatResponse || !wechatResponse.isSuccess()) {
            rglog.error("调用微信服务失败....");
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!McpsParamConstant.DUBBO_SUCCESS.equals(wechatResponse.getResult().getRespCode())) {
            rglog.error("调用微信服务失败,errorCode:<{}>,errorMsg:<{}>", wechatResponse.getResult().getRespCode(), wechatResponse.getResult().getRespDesc());
            throw new BizException(wechatResponse.getResult().getRespCode(), wechatResponse.getResult().getRespDesc());
        }
        return wechatResponse.getResult().getAuthUrl();
    }

    /**
     * 支付宝获取authCode 调用通道
     *
     * @param request 请求体
     * @param mchntNo 商户号
     * @return authUrl
     * @throws Exception 异常
     */
    private String aliGetAuthCodeUrl(GetUserAuthCodeRequest request, String mchntNo) throws Exception {

        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();

        //获取通道服务调用配置
        List<ChannelCallCfg> txnNumList = txnInfo.getChannelCallCfgList().stream().filter(item -> ChannelEnum.ALIP.getChannelType().equals(item.getCallChannelId())).collect(Collectors.toList());
        if (txnNumList.isEmpty()) {
            rglog.error("未配置支付宝用户授权的通道交易映射关系");
            throw new BizException(RespCodeEnum.SYSTEM_ERROR.getRespCode(), RespCodeEnum.SYSTEM_ERROR.getRespDesc());
        }

        //获取支付宝商户信息
//        AlipayMchntInfoMapper alipayMchntInfoMapper = new AlipayMchntInfoMapperImpl();
//        AlipayMchntInfo alipayMchntInfo = alipayMchntInfoMapper.selectAlipayMchntInfoByPrimaryKey(request.getHeader().getInstId(), mchntNo);
//        if (null == alipayMchntInfo) {
//            rglog.error("支付宝商户信息表不存在该商户信息,查询基本商户信息");
//            MchntBaseInfoMapper mchntBaseInfoMapper = new MchntBaseInfoMapperImpl();
//            MchntBaseInfo mchntBaseInfo = mchntBaseInfoMapper.getMchntInf(mchntNo);
//            if (null != mchntBaseInfo && ("11").equals(mchntBaseInfo.getMchntType()) && McpsParamConstant.OPMS_PARAM_NO.equals(mchntBaseInfo.getIndependentDataFlag())) {
//                rglog.debug("非独立清算商户,查询连锁商户信息");
//                if (!StringUtil.isEmptyOrNull(mchntBaseInfo.getChainMchntNo())) {
//                    rglog.debug("查询连锁商户的微信商户信息");
//                    alipayMchntInfo = alipayMchntInfoMapper.selectAlipayMchntInfoByPrimaryKey(request.getHeader().getInstId(), mchntBaseInfo.getChainMchntNo());
//                }
//            }
//        }
//        if (null == alipayMchntInfo) {
//            rglog.info("当前商户的支付宝商户信息不存在...");
//            throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
//        }

        cc.rengu.igas.channel.alipay.facade.base.Header alipayHeader = new cc.rengu.igas.channel.alipay.facade.base.Header();
        alipayHeader.setVersion("1.0.0");
        alipayHeader.setTransDate(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_DATE));
        alipayHeader.setTransTime(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.TRANS_TIME));
        alipayHeader.setTxnNum(txnNumList.get(0).getCallChannelTxn());
        alipayHeader.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        alipayHeader.setInstId(request.getHeader().getInstId());
        alipayHeader.setSrcSysId(AppParamConstant.IGAS);
        alipayHeader.setChanlId(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SRC_SYS_ID));
        alipayHeader.setTraceNo(xmlTreeUtil.getXmlTreeStringValue(TreeNodeConstant.SYS_SEQ_NUM) + txnNumList.get(0).getCallIndex());

        AliGetAuthCodeRequest aliGetAuthCodeRequest = new AliGetAuthCodeRequest();
        aliGetAuthCodeRequest.setHeader(alipayHeader);
        aliGetAuthCodeRequest.setRedirectUrl(request.getRedirectUrl());
        aliGetAuthCodeRequest.setChannelId(ChannelEnum.ALIP.getChannelType());
//        String qrCode = request.getQrCode();
//        int index = qrCode.indexOf("inf=");
//        aliGetAuthCodeRequest.setState(qrCode.substring(index + 4));
        rglog.debug("dubbo请求体:<{}>", JSON.toJSONString(aliGetAuthCodeRequest));
        DubboService dubboService = new DubboServiceImpl();
        cc.rengu.igas.channel.alipay.facade.result.Result<AliGetAuthCodeResponse> aliResult;
        try {
            aliResult = (cc.rengu.igas.channel.alipay.facade.result.Result<AliGetAuthCodeResponse>) dubboService.callDubboService("alipayPubService", "aliGetAuthCode", aliGetAuthCodeRequest);
        } catch (Exception e) {
            rglog.error("支付宝获取authCode异常:<{}>", e);
            aliResult = null;
        }
        if (null == aliResult || !aliResult.isSuccess()) {
            rglog.error("调用支付宝服务失败....");
            throw new BizException(RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespCode(), RespCodeEnum.CALL_BIZ_SERVICE_ERROR.getRespDesc());
        } else if (!McpsParamConstant.DUBBO_SUCCESS.equals(aliResult.getResult().getRespCode())) {
            rglog.error("调用支付宝服务失败,errorCode:<{}>,errorMsg:<{}>", aliResult.getResult().getRespCode(), aliResult.getResult().getRespDesc());
            throw new BizException(aliResult.getResult().getRespCode(), aliResult.getResult().getRespDesc());
        }
        return aliResult.getResult().getAuthUrl();
    }
}
